OpenSSL compatibility for libodbc#10813
Conversation
|
ad3c910 to
b41bbac
Compare
|
Retest please. |
dgarske
left a comment
There was a problem hiding this comment.
Skoll Code Review
Scan type: reviewOverall recommendation: REQUEST_CHANGES
Findings: 7 total — 7 posted, 0 skipped
5 finding(s) posted as inline comments (see file-level comments below)
2 finding(s) not tied to a diff line (full detail below)
Posted findings
- [High] OBJ_find_sigid_algs stub hardcodes SHA-256/RSA and ignores sigid —
wolfssl/openssl/objects.h:81-88 - [Medium] No test coverage for WOLFSSL_VERIFY_NONE_DEFAULT security-relevant default change —
src/internal.c:2645-2649 - [Low] WOLFSSL_ERR_R_BUF_LIB defined as 0 (conflicts with 'no error' and OpenSSL's value) —
wolfssl/openssl/err.h:46 - [Low] Garbled comment on OBJ_find_sigid_algs literal NIDs —
wolfssl/openssl/objects.h:77-79 - [Low] TLS_ST_OK hardcoded to 16, coupled to internal enum position —
wolfssl/openssl/ssl.h:1572
Findings not tied to a diff line
SSL_R_UNKNOWN_PROTOCOL / WRONG_VERSION_NUMBER / UNSUPPORTED_PROTOCOL numeric value changed
File: wolfssl/openssl/ssl.h:1748-1753, wolfssl/openssl/err.h:47-49
Function: N/A (macros)
Severity: Medium
These three pre-existing public compat macros were changed from expanding to VERSION_ERROR (a negative wolfSSL internal error enum) to OpenSSL numeric reason codes (WOLFSSL_SSL_R_UNKNOWN_PROTOCOL=252, WOLFSSL_SSL_R_WRONG_VERSION_NUMBER=267, WOLFSSL_SSL_R_UNSUPPORTED_PROTOCOL=258). This is more OpenSSL-accurate, but it is a behavior change: any existing application that compared these macros against wolfSSL's internally reported error code (VERSION_ERROR, e.g. from wolfSSL_get_error/SSL_get_error) will no longer match, because wolfSSL still reports VERSION_ERROR internally, not 252/267/258. I confirmed there are no internal src/*.c or tests/*.c users of these specific macros (tests compare against VERSION_ERROR directly), so the build and current tests are unaffected, but downstream consumers relying on the old mapping would silently break.
Recommendation: Confirm this value change is intended and note it as a compatibility change in the PR/changelog. If wolfSSL's error surface (ERR_get_error/ERR_GET_REASON) does not translate internal VERSION_ERROR into these OpenSSL reason codes, apps checking reason == SSL_R_WRONG_VERSION_NUMBER will never match - verify the intended consumer (libodbc/libtds) actually reads these as raw constants and not via wolfSSL's error queue.
Referenced code: wolfssl/openssl/ssl.h:1748-1753, wolfssl/openssl/err.h:47-50 (4 lines)
BIO compat stubs have latent multi-use hazards (fixed index, app_data aliasing)
File: wolfssl/openssl/bio.h:196, wolfssl/openssl/ssl.h:1771-1774
Function: wolfSSL_BIO_get_new_index
Severity: Medium
Two BIO compat shims work for a single custom BIO but are unsafe if used more than once: (1) wolfSSL_BIO_get_new_index() always returns the constant 1000 - in OpenSSL each call returns a distinct index, so an app that registers two custom BIO types would get identical type values and collide. (2) BIO_get_app_data/BIO_set_app_data are mapped onto wolfSSL_BIO_get_data/wolfSSL_BIO_set_data, which is the SAME storage slot that a custom BIO method already uses for its method-private data. In OpenSSL these are two independent slots; collapsing them means an app that uses both BIO_set_data (method state) and BIO_set_app_data (app state) on the same BIO will overwrite one with the other. The wolfSSL_BIO_meth_get_* getters returning NULL and set_callback_ctrl being a no-op are acceptable documented stubs.
Recommendation: Keep for the narrow libodbc/libtds use, but document the single-custom-BIO limitation in the header comment. If feasible, back get_new_index with a static incrementing counter, and keep app_data in a separate slot from method data to avoid silent corruption when both are used.
Referenced code: wolfssl/openssl/bio.h:196, wolfssl/openssl/ssl.h:1771-1774 (4 lines)
Review generated by Skoll
|
@kojo1 can you rebase to latest master? That might resolve the CI issues |
dgarske
left a comment
There was a problem hiding this comment.
Skoll Code Review
Scan type: reviewOverall recommendation: COMMENT
Findings: 7 total — 6 posted, 1 skipped
6 finding(s) posted as inline comments (see file-level comments below)
Posted findings
- [Medium] OBJ_find_sigid_algs compat macro placed in ssl.h instead of objects.h with the other OBJ_ macros* —
wolfssl/openssl/ssl.h:1785 - [Medium] WOLFSSL_TLS_ST_OK hardcoded to 16, duplicating internal HANDSHAKE_DONE with no compile-time check —
wolfssl/openssl/ssl.h:1572-1577 - [Medium] BIO_get_app_data/BIO_set_app_data aliased to BIO_get_data/BIO_set_data (shared storage) —
wolfssl/openssl/ssl.h:1773-1775 - [Medium] No test coverage for new wolfSSL_OBJ_find_sigid_algs mapping logic —
wolfssl/openssl/objects.h:79-127 - [Low] BIO compat stubs report success/fixed values with silent limitations —
wolfssl/openssl/bio.h:194-220 - [Low] wolfSSL_OBJ_find_sigid_algs omits RSA-PSS, EdDSA, and MD5 signature NIDs —
wolfssl/openssl/objects.h:83-121
Skipped findings
- [Medium]
SSL_R_* compat macros silently change value from VERSION_ERROR to positive OpenSSL codes
Review generated by Skoll
| #define BIO_meth_get_callback_ctrl wolfSSL_BIO_meth_get_callback_ctrl | ||
| #define BIO_meth_set_callback_ctrl wolfSSL_BIO_meth_set_callback_ctrl | ||
| #ifndef BUILDING_WOLFSSL | ||
| #define OBJ_find_sigid_algs wolfSSL_OBJ_find_sigid_algs |
There was a problem hiding this comment.
🟠 [Medium] OBJ_find_sigid_algs compat macro placed in ssl.h instead of objects.h with the other OBJ_ macros*
Every other OBJ_* -> wolfSSL_OBJ_* compat macro is defined in wolfssl/openssl/objects.h (lines 53-69), co-located with the function it aliases. This PR defines the function wolfSSL_OBJ_find_sigid_algs in objects.h but puts the #define OBJ_find_sigid_algs wolfSSL_OBJ_find_sigid_algs alias in ssl.h (broad OPENSSL_EXTRA block), decoupling the macro from its definition. ssl.h only #includes objects.h under WOLFSSL_QT || OPENSSL_ALL (line 52-55); it works for plain OPENSSL_EXTRA builds only because evp.h happens to include objects.h at its tail. This transitive dependency is fragile: any build path where evp.h is skipped (e.g. WOLFCRYPT_ONLY) would define the macro while leaving wolfSSL_OBJ_find_sigid_algs undeclared, yielding an implicit-declaration error at the call site.
Fix: Move the #define OBJ_find_sigid_algs wolfSSL_OBJ_find_sigid_algs into objects.h next to the function definition and the other OBJ_* aliases, so the macro and its target are always defined together.
| #define SSL_get_state wolfSSL_get_state | ||
| #define SSL_state_string_long wolfSSL_state_string_long | ||
|
|
||
| /* Must equal HANDSHAKE_DONE in the internal 'enum states' |
There was a problem hiding this comment.
🟠 [Medium] WOLFSSL_TLS_ST_OK hardcoded to 16, duplicating internal HANDSHAKE_DONE with no compile-time check
WOLFSSL_TLS_ST_OK (and its aliases TLS_ST_OK/SSL_ST_OK) is hardcoded to 16 to match HANDSHAKE_DONE in the private enum states (wolfssl/internal.h). The value is correct today (HANDSHAKE_DONE is the 17th enumerator, index 16, and wolfSSL_get_state() returns ssl->options.handShakeState), but the coupling is a magic number with no static assertion. The comment even admits 16 today. Because internal.h isn't a public header, a static_assert can't live in the public header, so a silent drift is possible if a state is ever inserted before HANDSHAKE_DONE (the enum comment warns this also breaks session import).
Fix: Add a compile-time check in a .c file that includes internal.h, e.g. wc_static_assert(WOLFSSL_TLS_ST_OK == HANDSHAKE_DONE);, so any future enum drift fails the build instead of silently returning a wrong state constant.
| #define ERR_R_BUF_LIB WOLFSSL_ERR_R_BUF_LIB | ||
| #define BIO_TYPE_DESCRIPTOR WOLFSSL_BIO_TYPE_DESCRIPTOR | ||
| #define BIO_TYPE_SOURCE_SINK WOLFSSL_BIO_TYPE_SOURCE_SINK | ||
| #define BIO_get_app_data(bio) wolfSSL_BIO_get_data(bio) |
There was a problem hiding this comment.
🟠 [Medium] BIO_get_app_data/BIO_set_app_data aliased to BIO_get_data/BIO_set_data (shared storage)
In OpenSSL, BIO_set_data/BIO_get_data access the method-implementation pointer, while BIO_set_app_data/BIO_get_app_data access separate application ex-data. This PR maps BIO_get_app_data/BIO_set_app_data onto the same wolfSSL_BIO_get_data/wolfSSL_BIO_set_data slot that BIO_get_data/BIO_set_data already use (bio.h:163-164). A custom source/sink BIO (the ODBC/FreeTDS transport this PR targets) that stores its connection state via BIO_set_data in its create/ctrl callbacks and also uses BIO_set_app_data for an application pointer will have the two collide - whichever is written last silently overwrites the other.
Fix: Back app_data with a distinct storage slot (e.g. BIO ex_data index) so it does not alias the method data pointer, or document the limitation prominently if the aliasing is acceptable for the intended consumers.
|
|
||
| /* OBJ_find_sigid_algs(): map a certificate signature-algorithm NID to its | ||
| * digest and public-key NIDs; returns 0 for unsupported algorithms. */ | ||
| #ifndef BUILDING_WOLFSSL |
There was a problem hiding this comment.
🟠 [Medium] No test coverage for new wolfSSL_OBJ_find_sigid_algs mapping logic
The PR adds a non-trivial mapping function (a switch over ~10 signature-algorithm NIDs producing digest+pkey NID pairs, returning 0 for unsupported), but adds no unit test for it. grep finds no reference to OBJ_find_sigid_algs in tests/, examples/, or testsuite/. Mapping tables are exactly the kind of code where a transposed NID pair would go unnoticed. The verifyNone default got a good targeted test (test_wolfSSL_CTX_verify_none_default); this helper deserves the same.
Fix: Add an api.c test that calls OBJ_find_sigid_algs for a couple of RSA and ECDSA sig NIDs, asserts the returned digest/pkey NIDs and return==1, verifies NULL out-params are tolerated, and asserts an unsupported NID returns 0 without touching the out-params.
| #define WOLFSSL_BIO_TYPE_DESCRIPTOR 0x0100 | ||
| #define WOLFSSL_BIO_TYPE_SOURCE_SINK 0x0400 | ||
|
|
||
| /* OpenSSL allocates a fresh BIO type index per call; wolfSSL |
There was a problem hiding this comment.
🔵 [Low] BIO compat stubs report success/fixed values with silent limitations
wolfSSL_BIO_get_new_index() returns a fixed 1000 for every call, so two distinct app-defined BIO types receive the same index and are indistinguishable if compared. wolfSSL_BIO_meth_set_callback_ctrl() is an always-success no-op that discards the callback and returns 1, which conflicts with the wolfSSL guideline of not shipping always-success stubs (a caller that relies on the callback later being invoked gets no indication it was dropped). The getters correctly return NULL. These mirror OpenSSL's return conventions and are documented in the comments, so this is a low-priority observation rather than a defect.
Fix: If uniqueness is ever needed, hand out a monotonically increasing index instead of a constant. Keep the comment explicit that callback_ctrl is unsupported so callers don't assume the callback fires.
| static WC_INLINE int | ||
| wolfSSL_OBJ_find_sigid_algs(int sigid, int *pdig, int *ppkey) | ||
| { | ||
| int dig = 0; |
There was a problem hiding this comment.
🔵 [Low] wolfSSL_OBJ_find_sigid_algs omits RSA-PSS, EdDSA, and MD5 signature NIDs
The mapping covers SHA1/224/256/384/512 with RSA and ECDSA but returns 0 (unsupported) for other algorithms wolfSSL/OpenSSL know, e.g. NID_rsassaPss (WC_NID_rsassaPss=912), Ed25519/Ed448, and md5WithRSAEncryption (WC_NID_md5WithRSAEncryption=99), all of which are already defined in evp.h. For EdDSA in particular, OpenSSL's OBJ_find_sigid_algs returns 1 with pkey set and digest = undef; returning 0 here diverges and may cause a compat consumer's certificate-algorithm introspection to treat those certs as unknown. This is acceptable as a documented limitation for the current use case but is a divergence from OpenSSL semantics.
Fix: Consider extending the switch (guarded by the relevant feature macros) to cover RSA-PSS and Ed25519/Ed448 to match OpenSSL, or note the intentional scope limitation in the function comment.
Description
OpenSSL compatibility for libodbc.
Fixes zd#21884
Testing
Integration test with:
[ODBC application]
↓ unixODBC (libodbc.2)
├─→ psqlodbcw.so ─→ libpq.5.dylib ─┐
└─→ libtdsodbc.so ─────────┴─→ libwolfssl.44.dylib
Checklist